package com.bcfn.bshop.common.utils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 
 * @author LiangGuoNing.
 * 
 * 2019年1月18日 下午6:04:02.
 *
 * 修改记录：
 *
 */
public class ReflectUtil {
	
	static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	
	public static void setFieldValue(Object target, String fname, Class<?> ftype,Object fvalue) {
		if (target == null
				|| fname == null
				|| "".equals(fname)
				|| (fvalue != null && !ftype.isAssignableFrom(fvalue.getClass()))) {
			return;
		}
		Class<?> clazz = target.getClass();
		try {
			Method method = clazz.getDeclaredMethod("get" + Character.toUpperCase(fname.charAt(0)) + fname.substring(1), ftype);
			if (!Modifier.isPublic(method.getModifiers())) {
				method.setAccessible(true);
			}
			method.invoke(target, fvalue);
		} catch (Exception me) {
			me.printStackTrace();
			
			try {
				Field field = clazz.getDeclaredField(fname);
				if (!Modifier.isPublic(field.getModifiers())) {
					field.setAccessible(true);
				}
				field.set(target, fvalue);
			} catch (Exception fe) {
				fe.printStackTrace();
			}
		}
	}

	public static Field[] getAllFields(Class<?> klass) {
		List<Field> fields = new ArrayList<Field>();
		fields.addAll(Arrays.asList(klass.getDeclaredFields()));
		if (klass.getSuperclass() != null) {
			fields.addAll(Arrays.asList(getAllFields(klass.getSuperclass())));
		}
		return fields.toArray(new Field[] {});
	}

	public static Map<String, Field> getAllFieldsToMap(Class<?> clazz) {
		Field[] fields = getAllFields(clazz);
		Map<String, Field> result = new HashMap<String, Field>();
		if (fields != null) {
			for (Field field : fields) {
				result.put(field.getName(), field);
			}
		}
		return result;
	}

	public static Method[] getAllSetMethod(Class<?> klass) {
		return getMethodStartWith(klass, "set");
	}
	
	public static Method[] getAllGetMethod(Class<?> klass) {
		return getMethodStartWith(klass, "get");
	} 
	
	public static Method[] getMethodStartWith(Class<?> klass, String pattern) {
		List<Method> methods = new ArrayList<Method>();
		Method[] mds = klass.getDeclaredMethods();
		for(Method method : mds) {
			if (method.getName().startsWith(pattern)) {
				methods.add(method);
			}
		}
		
		if (klass.getSuperclass() != null) {
			methods.addAll(Arrays.asList(getMethodStartWith(klass.getSuperclass(), pattern)));
		}
		return methods.toArray(new Method[] {});
	} 
	
	public static Map<String, Method> getAllGetMethodsToMap(Class<?> clazz) {
		return getMethodsStartWithToMap(clazz, "get");
	}
	
	public static Map<String, Method> getAllSetMethodsToMap(Class<?> clazz) {
		return getMethodsStartWithToMap(clazz, "set");
	}
	
	private static Map<String, Method> getMethodsStartWithToMap(Class<?> clazz, String pattern) {
		Method[] methods = getMethodStartWith(clazz, pattern);
		Map<String, Method> result = new HashMap<String, Method>();
		if (methods != null) {
			for (Method method : methods) {
				result.put(method.getName(), method);
			}
		}
		return result;
	}
	
	public static Object invokeMethodByName(String className, String methodName, Object bean, Object[] argList) throws Exception {
		Method mtd = null;
		try{
			Class<?> svcClz = Class.forName(className);
			Class<?>[] argClzs = null;
			int size = argList.length;
			argClzs = new Class[size];
			for(int i = 0; i < size; i++) {
				argClzs[i] = argList[i].getClass();
			}
			mtd = svcClz.getMethod(methodName, argClzs);
		}catch(Exception ce){
			throw ce;
		}
		return mtd.invoke(bean, argList);
	}
}
